using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;

// TODO: replace these with the processor input and output types.
using TInput = System.String;
using TOutput = System.String;

namespace TerrainProcessor
{
    /// <summary>
    /// This class will be instantiated by the XNA Framework Content Pipeline
    /// to apply custom processing to content data, converting an object of
    /// type TInput to TOutput. The input and output types may be the same if
    /// the processor wishes to alter data without changing its type.
    ///
    /// This should be part of a Content Pipeline Extension Library project.
    ///
    /// TODO: change the ContentProcessor attribute to specify the correct
    /// display name for this processor.
    /// </summary>
    [ContentProcessor]
    public class ContentProcessor1 : ContentProcessor<Texture2DContent, ModelContent>
    {
        const float terrainScale = 3;
        const float terrainBumpiness = 128;
        const float textCoordScale = 1;
        const String terrainTexture = "rocks.bmp";

        public override ModelContent Process(Texture2DContent input, ContentProcessorContext context)
        {
            // TODO: process the input object, and return the modified data.
            MeshBuilder builder = MeshBuilder.StartMesh("terrain");

            input.ConvertBitmapType(typeof(PixelBitmapContent<float>));

            PixelBitmapContent<float> heightfield;
            heightfield = (PixelBitmapContent<float>)input.Mipmaps[0];

            //crear vertices

            for (int y = 0; y < heightfield.Height; y++)
            {
                for (int x = 0; x < heightfield.Width; x++)
                {
                    Vector3 position;

                    position.X = (x - heightfield.Width / 2) * terrainScale;
                    position.Z = (y - heightfield.Height / 2) * terrainScale;
                    position.Y = (heightfield.GetPixel(x, y) - 1) * terrainBumpiness;

                    builder.CreatePosition(position);
                }
            }

            // crear el material y apuntarlo a nuestra textura

            BasicMaterialContent material = new BasicMaterialContent();
            //            string directory = Path.GetDirectoryName(input.Identity.SourceFilename);
            //            string texture = Path.Combine(directory,terrainTexture);
            string texture = "../Content/heightmap.bmp";
            material.Texture = new ExternalReference<TextureContent>(texture);
            builder.SetMaterial(material);

            //crear el calan vertex para guardar las coordenadas de textura
            int texCoordId = builder.CreateVertexChannel<Vector2>(VertexChannelNames.TextureCoordinate(0));

            //crear los triangulos que hacen nuestro objeto mesh

            for (int y = 0; y < heightfield.Height - 1; y++)
            {
                for (int x = 0; x < heightfield.Width - 1; x++)
                {
                    AddVertex(builder, texCoordId, heightfield.Width, x, y);
                    AddVertex(builder, texCoordId, heightfield.Width, x + 1, y);
                    AddVertex(builder, texCoordId, heightfield.Width, x + 1, y + 1);

                    AddVertex(builder, texCoordId, heightfield.Width, x, y);
                    AddVertex(builder, texCoordId, heightfield.Width, x + 1, y + 1);
                    AddVertex(builder, texCoordId, heightfield.Width, x, y + 1);
                }
            }

            MeshContent terrainMesh = builder.FinishMesh();

            return context.Convert<MeshContent, ModelContent>(terrainMesh, "ModelProcessor");
        }

        static void AddVertex(MeshBuilder builder, int texCoordId, int w, int x, int y)
        {
            builder.SetVertexChannelData(texCoordId, new Vector2(x, y) / (textCoordScale * w));
            builder.AddTriangleVertex(x + y * w);
        }
    }

}